#include <log4cpp/Category.hh>
#include <log4cpp/Appender.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/Layout.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/Priority.hh>
using namespace log4cpp;

int main(void) {
    //输出器的部分
    // OstreamAppender构造函数的第一个参数表示目的地名称，只是一个提示
    // 第二个参数真正决定了日志的目的地址
    // 此处的
	Appender *appender1 = new OstreamAppender("console", &std::cout); // 多态，基类指针指向派生类对象
    
    // 目的地与布局绑定
	appender1->setLayout(new BasicLayout());

    // 准备的第二个输出器
    // FileAppender构造函数的第一个参数表示目的地名称，只是一个提示
    // 第二个参数表示将日志保存到的文件名
	Appender *appender2 = new FileAppender("default", "program.log");
    // 目的地与布局绑定
	appender2->setLayout(new BasicLayout());

    // 记录器
    // 类似单例模式
	Category& root = Category::getRoot();   // 创建了root节点的记录器
	root.setPriority(Priority::WARN);       // 记录器设置系统优先级，当优先级高于Priority::WARN时，才真正处理
	root.addAppender(appender1);            // 通过记录器绑定目的地

    //引用名sub1仅仅只是代码种使用的名字，用来绑定叶子节点的对象
    // getInstance中的sub1才是叶子节点真正的名字
	Category& sub1 = Category::getInstance("sub1"); // 创建了root节点之下的叶子节点（也是记录器）
	// Category& sub11 = Category::getInstance("sub1.sub11"); // 创建了sub1节点之下的叶子节点sub11
	sub1.addAppender(appender2); //继承root节点输出到console，而且还新增了一个目的地，输出到文件default

    // 也可以不继承父节点的目的地
    // sub1.setAdditivity(false); // 不使用root节点的输出器

	// use of functions for logging messages
	root.error("root error");   // 输出到终端
	root.info("root info");     // 过滤掉
	sub1.error("sub1 error");   // 输出到终端和文件
	sub1.warn("sub1 warn");     // 输出到终端和文件

	// printf-style for logging variables
	root.warn("%d + %d == %s ?", 1, 1, "two"); // 输出到终端

	// use of streams for logging messages 很少用
	root << Priority::ERROR << "Streamed root error";
	root << Priority::INFO << "Streamed root info";
	sub1 << Priority::ERROR << "Streamed sub1 error";
	sub1 << Priority::WARN << "Streamed sub1 warn";

	// or this way:
	root.errorStream() << "Another streamed error";

	return 0;
}